package pl.edu.politechnika.zio.qfl.controller;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import com.restfb.Connection;
import com.restfb.DefaultFacebookClient;
import com.restfb.FacebookClient;
import com.restfb.Parameter;
import com.restfb.types.FacebookType;
import com.restfb.types.User;

@Controller
// http://localhost:8080/aplikacja...
@RequestMapping("/")
public class FacebookController {
    private static final Logger log = LoggerFactory
            .getLogger(FacebookController.class);

    private static final String REDIRECT_MAPPING = "2";
    private String appKey;
    private String appSecret;
    private String appHost;
    private String accessFlags;

    @Value("#{properties.facebook_app_id}")
    public void setAppKey(String appKey) {
        this.appKey = appKey;
    }

    @Value("#{properties.facebook_app_secret}")
    public void setAppSecret(String appSecret) {
        this.appSecret = appSecret;
    }

    @Value("#{properties.facebook_app_access_flags}")
    public void setAccessFlags(String accessFlags) {
        this.accessFlags = accessFlags;
    }

    @Value("#{properties.facebook_app_host}")
    public void setAppHost(String appHost) {
        this.appHost = appHost;
    }
    
    @RequestMapping(method = RequestMethod.GET)
    public String phaseOne() {
        if (log.isDebugEnabled()) {
            log.debug("FacebookController - phase 1 has begun.");
        }

        StringBuilder url = new StringBuilder(
                "https://www.facebook.com/dialog/oauth?").append("client_id=")
                .append(appKey).append("&redirect_uri=").append(appHost)
                .append(REDIRECT_MAPPING);

        if (accessFlags != null) {
            url = url.append("&scope=").append(accessFlags);
        }

        if (log.isDebugEnabled()) {
            log.debug("BUILT URL: {}", url.toString());
            log.debug("FacebookController - phase 1 has ended.");
        }

        return String.format("redirect:%s", url.toString());
    }

    @RequestMapping(value = "2", method = RequestMethod.GET)
    public String phaseTwo(@RequestParam("code")
    String code) {
        if (log.isDebugEnabled()) {
            log.debug("FacebookController - phase 2 has begun.");
        }

        if (code == null || code.isEmpty()) {
            if (log.isDebugEnabled()) {
                log.debug("'code' parameter is null");
            }
            return "error";
        }

        // Build URL.
        StringBuilder url = new StringBuilder(
                "https://graph.facebook.com/oauth/access_token?")
                .append("client_id=").append(appKey).append("&redirect_uri=")
                .append(appHost).append(REDIRECT_MAPPING)
                .append("&client_secret=").append(appSecret).append("&code=")
                .append(code);

        // Fetch HTML.
        StringBuilder input;
        try {
            URL tokenUrl = new URL(url.toString());
            URLConnection urlConn = tokenUrl.openConnection();
            BufferedReader in = new BufferedReader(new InputStreamReader(
                    urlConn.getInputStream()));

            input = new StringBuilder();
            String inputLine;
            while ((inputLine = in.readLine()) != null)
                input = input.append(inputLine);
            in.close();
        } catch (Exception ex) {
            if (log.isDebugEnabled()) {
                log.debug("Problem with requesting access token.");
            }
            return "error";
        }

        // Parse HTML into token and expire values.
        String accessToken = "";
        String expires = "";

        String[] params = input.toString().split("&");
        if (params.length == 2) {
            String token = params[0];
            String[] token_value = token.split("=");
            if (token_value.length == 2) {
                accessToken = token_value[1];
            }

            String exp = params[1];
            String[] exp_value = exp.split("=");
            if (exp_value.length == 2) {
                expires = exp_value[1];
            }
        }

        if (accessToken.isEmpty() || expires.isEmpty()) {
            if (log.isDebugEnabled()) {
                log.debug("Access token or expire value were empty.");
            }
            return "error";
        }

        // Load friendlist.
        FacebookClient facebookClient = new DefaultFacebookClient(accessToken);

        Connection<User> myFriends = facebookClient.fetchConnection(
                "me/friends", User.class);

        StringBuilder friends = new StringBuilder();
        for (User u : myFriends.getData()) {
            friends = friends.append(u.getName()).append("\n");
        }
        log.debug("Friends: " + friends.toString());

        // Facebook POST test.
        try {
            facebookClient.publish("me/feed", FacebookType.class, Parameter
                    .with("message",
                            "Testing RestFB client for Facebook Graph API."));
        } catch (Exception ex) {
            log.debug("Facebook thinks we're spamming wall. Duplicate error.");
        }

        return "success?friends=" + friends.toString();
    }

    @RequestMapping(value = "success", method = RequestMethod.GET)
    public String phaseSuccess(@RequestParam("friends")
    String friends) {
        return null;
    }
}
